package com.LachesismStorm.lachesism.member.util;

import java.time.LocalDate;
import java.util.HashMap;
import java.util.Map;

import static com.LachesismStorm.lachesism.core.common.enums.CommonEnum.*;

/**
 * @Author lachesism
 * @Date 2024-07-07 20:38
 **/
public class ConstellationUtil {



    private static final Map<Integer, Integer> birthMonthParams = new HashMap<>();
    private static final Map<Integer, String> risingSignTimes = new HashMap<>();

    static {
        birthMonthParams.put(1, 400);
        birthMonthParams.put(2, 523);
        birthMonthParams.put(3, 633);
        birthMonthParams.put(4, 755);
        birthMonthParams.put(5, 873);
        birthMonthParams.put(6, 996);
        birthMonthParams.put(7, 1114);
        birthMonthParams.put(8, 1236);
        birthMonthParams.put(9, 1358);
        birthMonthParams.put(10, 37);
        birthMonthParams.put(11, 159);
        birthMonthParams.put(12, 277);
        risingSignTimes.put(1080, "白羊座");
        risingSignTimes.put(1169, "金牛座");
        risingSignTimes.put(1271, "双子座");
        risingSignTimes.put(1393, "巨蟹座");
        risingSignTimes.put(89, "狮子座");
        risingSignTimes.put(226, "处女座");
        risingSignTimes.put(360, "天秤座");
        risingSignTimes.put(493, "天蝎座");
        risingSignTimes.put(630, "射手座");
        risingSignTimes.put(766, "摩羯座");
        risingSignTimes.put(888, "水瓶座");
        risingSignTimes.put(990, "双鱼座");
    }


    // 简化的算法，用于演示如何根据出生日期估算太阳星座
    public static String getZodiacSign(int month, int day) {
        if (month < 1 || month > 12 || day < 1 || day > 31) {
            return "日期无效";
        }
        if ((month == 3 && day >= 21) || (month == 4 && day <= 19)) {
            return "白羊座";
        } else if ((month == 4 && day >= 20) || (month == 5 && day <= 20)) {
            return "金牛座";
        } else if ((month == 5 && day >= 21) || (month == 6 && day <= 21)) {
            return "双子座";
        } else if ((month == 6 && day >= 22) || (month == 7 && day <= 22)) {
            return "巨蟹座";
        } else if ((month == 7 && day >= 23) || (month == 8 && day <= 22)) {
            return "狮子座";
        } else if ((month == 8 && day >= 23) || (month == 9 && day <= 22)) {
            return "处女座";
        } else if ((month == 9 && day >= 23) || (month == 10 && day <= 23)) {
            return "天秤座";
        } else if ((month == 10 && day >= 24) || (month == 11 && day <= 22)) {
            return "天蝎座";
        } else if ((month == 11 && day >= 23) || (month == 12 && day <= 21)) {
            return "射手座";
        } else if ((month == 12 && day >= 22) || (month == 1 && day <= 19)) {
            return "摩羯座";
        } else if ((month == 1 && day >= 20) || (month == 2 && day <= 18)) {
            return "水瓶座";
        } else if ((month == 2 && day == 29)) {
            return "双鱼座";
        } else if ((month == 2 && day >= 19) || (month == 3 && day <= 20)) {
            return "双鱼座";
        } else {
            return "未知星座";
        }
    }

    // 简化的算法，用于演示如何根据出生日期估算月亮星座
    public static String estimateMoonSign(int birthYear, int birthMonth, int birthDay) {
        // 将出生日期转换为天数（从某个固定日期开始计算）
        LocalDate birthDate = LocalDate.of(birthYear, birthMonth, birthDay);
        long daysSinceEpoch = birthDate.toEpochDay();
        // 估算月亮周期（大约29.5天）
        double moonCycleDays = 29.5;
        // 估算月亮在黄道带上的位置（0-360度）
        double moonPosition = (daysSinceEpoch % (moonCycleDays * 12)) / moonCycleDays * 360;

        // 将月亮位置转换为星座（每个星座大约30度）
        int moonSignIndex = (int) (moonPosition / 30);
        String[] moonSigns = {
                "白羊座", "金牛座", "双子座", "巨蟹座", "狮子座", "处女座",
                "天秤座", "天蝎座", "射手座", "摩羯座", "水瓶座", "双鱼座"
        };
        // 返回月亮星座
        return moonSigns[moonSignIndex % 12];
    }


    public static void main(String[] args) {
        // 示例出生日期
        int birthYear = 1997;
        int birthMonth = 10;
        int birthDay = 15;
        int hour = 21;
        int minute = 55;
        // 计算月亮星座
        String moonSign = estimateMoonSign(birthYear, birthMonth, birthDay);
        String zodiacSigns = getZodiacSign(birthMonth, birthDay);
        String ascendant = calculateAscendant(birthMonth, birthDay, hour, minute);
        int index = 0;
        for (int i = 0; i < ZODIAC_SIGNS.length; i++) {
            if (ZODIAC_SIGNS[i].equals(ascendant)) {
                index = i;
                break;
            }
        }
        System.out.println("宫主星：" + ZODIAC_SIGNS[index]);
        for (int i = 1; i <= 12; i++) {
            int houseIndex = (index + i) % 12;
            System.out.println("第" + i + "宫：" + ZODIAC_SIGNS[houseIndex]);
        }

        System.out.println("根据出生日期算的太阳星座是: " + zodiacSigns);
        System.out.println("根据出生日期算的月亮星座是: " + moonSign);
        System.out.println("根据出生日期算的上升星座是: " + ascendant);
        double julianDate = calculateJulianDate(birthYear, birthMonth, birthDay);
        System.out.println(birthYear + "-" + birthMonth + "-" + birthDay + "儒略日为: " + julianDate);
        // 计算星球位置
        Map<String, Double> stringDoubleMap = calculatePlanetPosition(julianDate);
        System.out.println("当天地球位置为: " + stringDoubleMap.get("earthPosition") + " AU");
        System.out.println("当天火星位置为: " + stringDoubleMap.get("marsPosition") + " AU");
        System.out.println("当天金星位置为: " + stringDoubleMap.get("venusPosition") + " AU");
        System.out.println("当天水星位置为: " + stringDoubleMap.get("mercuryPosition") + " AU");
        System.out.println("当天木星位置为: " + stringDoubleMap.get("jupiterPosition") + " AU");
        System.out.println("当天月亮位置为: " + stringDoubleMap.get("moonPosition") + " AU");
        System.out.println("当天土星位置为: " + stringDoubleMap.get("saturnPosition") + " AU");
        System.out.println("当天天王星位置为: " + stringDoubleMap.get("uranusPosition") + " AU");
        System.out.println("当天海王位置为: " + stringDoubleMap.get("neptunePosition") + " AU");
        System.out.println("当天冥王星位置为: " + stringDoubleMap.get("plutoPosition") + " AU");
        System.out.println("(AU是天文单位（Astronomical Unit）的缩写，它是用于测量天体之间距离的一种单位。1 AU 定义为地球与太阳之间的平均距离，大约等于149,597,870.7公里（约92,955,807英里）。这个距离被用作一个标准，用来描述太阳系内其他行星与太阳之间的距离，以及行星之间的相对距离。)");
    }


    public static String calculateAscendant(int month, int day, int hour, int minute) {
        Integer monthNum = birthMonthParams.get(month);
        Integer dayNum = day * 4;
        Integer birthNum = (hour * 60) + minute;
        Integer totalNum = monthNum + dayNum + birthNum;
        if (totalNum >= 1440) {
            totalNum = totalNum - 1440;
        }
        return findClosestRisingSign(totalNum);
    }

    private static String findClosestRisingSign(int totalMinutes) {
        String closestSign = "未知"; // 默认值，如果找不到匹配项
        int closestDifference = Integer.MAX_VALUE;
        for (Map.Entry<Integer, String> entry : risingSignTimes.entrySet()) {
            int time = entry.getKey();
            String sign = entry.getValue();
            // 计算当前星座和totalMinutes的差异
            int difference;
            if (totalMinutes >= time) {
                difference = totalMinutes - time;
            } else {
                difference = 1440 - time + totalMinutes;
            }
            // 检查是否是找到的最小差异
            if (difference < closestDifference) {
                closestDifference = difference;
                closestSign = sign;
            }
        }

        return closestSign;
    }


    // 计算给定儒略日的太阳系行星位置
    public static Map<String, Double> calculatePlanetPosition(double julianDate) {
        HashMap<String, Double> planetPosition = new HashMap<>();
        // 儒略日参考点，通常使用2000年1月1日的儒略日
        final double JULIAN_DATE_REFERENCE = 2451545.0;
        // 将儒略日转换为相对于参考点的天数
        // 然后除以对应的行星公转周期，得到公转周期内的分数位置
        double earthOrbitFraction = (julianDate - JULIAN_DATE_REFERENCE) / EARTH_ORBITAL_PERIOD;
        double marsOrbitFraction = (julianDate - JULIAN_DATE_REFERENCE) / MARS_ORBITAL_PERIOD;
        double venusOrbitFraction = (julianDate - JULIAN_DATE_REFERENCE) / VENUS_ORBITAL_PERIOD;
        double mercuryOrbitFraction = (julianDate - JULIAN_DATE_REFERENCE) / MERCURY_ORBITAL_PERIOD;
        double jupiterOrbitFraction = (julianDate - JULIAN_DATE_REFERENCE) / JUPITER_ORBITAL_PERIOD;
        double moonOrbitFraction = (julianDate - JULIAN_DATE_REFERENCE) / MOON_ORBITAL_PERIOD;
        double saturnOrbitFraction = (julianDate - JULIAN_DATE_REFERENCE) / SATURN_ORBITAL_PERIOD;
        double uranusOrbitFraction = (julianDate - JULIAN_DATE_REFERENCE) / URANUS_ORBITAL_PERIOD;
        double neptuneOrbitFraction = (julianDate - JULIAN_DATE_REFERENCE) / NEPTUNE_ORBITAL_PERIOD;
        double plutoOrbitFraction = (julianDate - JULIAN_DATE_REFERENCE) / PLUTO_ORBITAL_PERIOD;
        // 计算各个行星的真近点角（True Anomaly），这是行星在轨道上的实际角度位置
        double trueEarthAnomaly = 2 * Math.PI * earthOrbitFraction;
        double trueMarsAnomaly = 2 * Math.PI * marsOrbitFraction;
        double trueVenusAnomaly = 2 * Math.PI * venusOrbitFraction;
        double trueMercuryAnomaly = 2 * Math.PI * mercuryOrbitFraction;
        double trueJupiterAnomaly = 2 * Math.PI * jupiterOrbitFraction;
        double trueMoonAnomaly = 2 * Math.PI * moonOrbitFraction;
        double trueSaturnAnomaly = 2 * Math.PI * saturnOrbitFraction;
        double trueUranusAnomaly = 2 * Math.PI * uranusOrbitFraction;
        double trueNeptuneAnomaly = 2 * Math.PI * neptuneOrbitFraction;
        double truePlutoAnomaly = 2 * Math.PI * plutoOrbitFraction;
        // 使用开普勒方程迭代求解行星的偏近点角（Eccentric Anomaly）
        // 开普勒方程是求解行星运动的方程，这里使用迭代法逼近解
        double eccentricEarthAnomaly = trueEarthAnomaly + EARTH_ORBITAL_ECCENTRICITY * Math.sin(trueEarthAnomaly);
        for (int i = 0; i < 10; i++) {
            double f = eccentricEarthAnomaly - EARTH_ORBITAL_ECCENTRICITY * Math.sin(eccentricEarthAnomaly) - trueEarthAnomaly;
            double fPrime = 1 - EARTH_ORBITAL_ECCENTRICITY * Math.cos(eccentricEarthAnomaly);
            eccentricEarthAnomaly -= f / fPrime;
        }
        double eccentricMarsAnomaly = trueMarsAnomaly + MARS_ORBITAL_ECCENTRICITY * Math.sin(trueMarsAnomaly);
        for (int i = 0; i < 10; i++) {
            double f = eccentricMarsAnomaly - MARS_ORBITAL_ECCENTRICITY * Math.sin(eccentricMarsAnomaly) - trueMarsAnomaly;
            double fPrime = 1 - MARS_ORBITAL_ECCENTRICITY * Math.cos(eccentricMarsAnomaly);
            eccentricMarsAnomaly -= f / fPrime;
        }
        double eccentricVenusAnomaly = trueVenusAnomaly + VENUS_ORBITAL_ECCENTRICITY * Math.sin(trueVenusAnomaly);
        for (int i = 0; i < 10; i++) {
            double f = eccentricVenusAnomaly - VENUS_ORBITAL_ECCENTRICITY * Math.sin(eccentricVenusAnomaly) - trueVenusAnomaly;
            double fPrime = 1 - VENUS_ORBITAL_ECCENTRICITY * Math.cos(eccentricVenusAnomaly);
            eccentricVenusAnomaly -= f / fPrime;
        }
        double eccentricMercuryAnomaly = trueMercuryAnomaly + MERCURY_ORBITAL_ECCENTRICITY * Math.sin(trueMercuryAnomaly);
        for (int i = 0; i < 10; i++) {
            double f = eccentricMercuryAnomaly - MERCURY_ORBITAL_PERIOD * Math.sin(eccentricMercuryAnomaly) - trueMercuryAnomaly;
            double fPrime = 1 - MERCURY_ORBITAL_ECCENTRICITY * Math.cos(eccentricMercuryAnomaly);
            eccentricMercuryAnomaly -= f / fPrime;
        }
        double eccentricJupiterAnomaly = trueJupiterAnomaly + JUPITER_ORBITAL_ECCENTRICITY * Math.sin(trueJupiterAnomaly);
        for (int i = 0; i < 10; i++) {
            double f = eccentricJupiterAnomaly - JUPITER_ORBITAL_PERIOD * Math.sin(eccentricJupiterAnomaly) - trueJupiterAnomaly;
            double fPrime = 1 - JUPITER_ORBITAL_ECCENTRICITY * Math.cos(eccentricJupiterAnomaly);
            eccentricJupiterAnomaly -= f / fPrime;
        }
        double eccentricMoonAnomaly = trueMoonAnomaly + MOON_ORBITAL_ECCENTRICITY * Math.sin(trueMoonAnomaly);
        for (int i = 0; i < 10; i++) {
            double f = eccentricMoonAnomaly - MOON_ORBITAL_PERIOD * Math.sin(eccentricMoonAnomaly) - trueMoonAnomaly;
            double fPrime = 1 - MOON_ORBITAL_ECCENTRICITY * Math.cos(eccentricMoonAnomaly);
            eccentricMoonAnomaly -= f / fPrime;
        }
        double eccentricSaturnAnomaly = trueSaturnAnomaly + SATURN_ORBITAL_PERIOD * Math.sin(trueSaturnAnomaly);
        for (int i = 0; i < 10; i++) {
            double f = eccentricSaturnAnomaly - SATURN_ORBITAL_PERIOD * Math.sin(eccentricSaturnAnomaly) - trueSaturnAnomaly;
            double fPrime = 1 - SATURN_ORBITAL_ECCENTRICITY * Math.cos(eccentricSaturnAnomaly);
            eccentricSaturnAnomaly -= f / fPrime;
        }
        double eccentricUranusAnomaly = trueUranusAnomaly + URANUS_ORBITAL_PERIOD * Math.sin(trueUranusAnomaly);
        for (int i = 0; i < 10; i++) {
            double f = eccentricUranusAnomaly - URANUS_ORBITAL_PERIOD * Math.sin(eccentricUranusAnomaly) - trueUranusAnomaly;
            double fPrime = 1 - URANUS_ORBITAL_ECCENTRICITY * Math.cos(eccentricUranusAnomaly);
            eccentricUranusAnomaly -= f / fPrime;
        }
        double eccentricNeptuneAnomaly = trueNeptuneAnomaly + NEPTUNE_ORBITAL_PERIOD * Math.sin(trueNeptuneAnomaly);
        for (int i = 0; i < 10; i++) {
            double f = eccentricNeptuneAnomaly - NEPTUNE_ORBITAL_PERIOD * Math.sin(eccentricNeptuneAnomaly) - trueNeptuneAnomaly;
            double fPrime = 1 - NEPTUNE_ORBITAL_ECCENTRICITY * Math.cos(eccentricNeptuneAnomaly);
            eccentricNeptuneAnomaly -= f / fPrime;
        }
        double eccentricPlutoAnomaly = truePlutoAnomaly + PLUTO_ORBITAL_PERIOD * Math.sin(truePlutoAnomaly);
        for (int i = 0; i < 10; i++) {
            double f = eccentricPlutoAnomaly - PLUTO_ORBITAL_PERIOD * Math.sin(eccentricPlutoAnomaly) - truePlutoAnomaly;
            double fPrime = 1 - PLUTO_ORBITAL_ECCENTRICITY * Math.cos(eccentricPlutoAnomaly);
            eccentricPlutoAnomaly -= f / fPrime;
        }

        // 计算行星在轨道上的位置，这里使用简化的开普勒方程求解器
        // 计算结果为行星与太阳之间的距离
        // 根据偏心率和偏近点角计算行星位置的辅助方法
        double earthPosition = Math.sqrt((1 + EARTH_ORBITAL_ECCENTRICITY) / (1 - EARTH_ORBITAL_ECCENTRICITY * Math.cos(eccentricEarthAnomaly)));
        double marsPosition = Math.sqrt((1 + MARS_ORBITAL_ECCENTRICITY) / (1 - MARS_ORBITAL_ECCENTRICITY * Math.cos(eccentricMarsAnomaly)));
        double venusPosition = Math.sqrt((1 + VENUS_ORBITAL_ECCENTRICITY) / (1 - VENUS_ORBITAL_ECCENTRICITY * Math.cos(eccentricVenusAnomaly)));
        double mercuryPosition = Math.sqrt((1 + MERCURY_ORBITAL_ECCENTRICITY) / (1 - MERCURY_ORBITAL_ECCENTRICITY * Math.cos(eccentricVenusAnomaly)));
        double jupiterPosition = Math.sqrt((1 + JUPITER_ORBITAL_ECCENTRICITY) / (1 - JUPITER_ORBITAL_ECCENTRICITY * Math.cos(eccentricVenusAnomaly)));
        double moonPosition = Math.sqrt((1 + MOON_ORBITAL_ECCENTRICITY) / (1 - MOON_ORBITAL_ECCENTRICITY * Math.cos(eccentricMoonAnomaly)));
        double saturnPosition = Math.sqrt((1 + SATURN_ORBITAL_ECCENTRICITY) / (1 - SATURN_ORBITAL_ECCENTRICITY * Math.cos(eccentricSaturnAnomaly)));
        double uranusPosition = Math.sqrt((1 + URANUS_ORBITAL_ECCENTRICITY) / (1 - URANUS_ORBITAL_ECCENTRICITY * Math.cos(eccentricUranusAnomaly)));
        double neptunePosition = Math.sqrt((1 + NEPTUNE_ORBITAL_ECCENTRICITY) / (1 - NEPTUNE_ORBITAL_ECCENTRICITY * Math.cos(eccentricNeptuneAnomaly)));
        double plutoPosition = Math.sqrt((1 + PLUTO_ORBITAL_ECCENTRICITY) / (1 - PLUTO_ORBITAL_ECCENTRICITY * Math.cos(eccentricPlutoAnomaly)));
        planetPosition.put("earthPosition", earthPosition);
        planetPosition.put("marsPosition", marsPosition);
        planetPosition.put("venusPosition", venusPosition);
        planetPosition.put("mercuryPosition", mercuryPosition);
        planetPosition.put("jupiterPosition", jupiterPosition);
        planetPosition.put("moonPosition", moonPosition);
        planetPosition.put("saturnPosition", saturnPosition);
        planetPosition.put("uranusPosition", uranusPosition);
        planetPosition.put("neptunePosition", neptunePosition);
        planetPosition.put("plutoPosition", plutoPosition);
        // 返回星球位置的径向距离
        return planetPosition;
    }

    //计算儒略日，传入年月日计算
    public static double calculateJulianDate(int year, int month, int day) {
        if (month <= 2) {
            year -= 1;
            month += 12;
        }
        int A = year / 100;
        int B = 2 - A + A / 4;
        return Math.floor(365.25 * (year + 4716)) + Math.floor(30.6001 * (month + 1)) + day + B - 1524.5;
    }

}
/*
星座运势分析是一种流行文化现象，它基于西方占星术，认为人的性格、行为和运势与出生时太阳、月亮和行星在黄道十二宫中的位置有关。虽然这种分析方法没有科学依据，但许多人仍然对其感兴趣。以下是进行星座运势分析时可能需要考虑的一些因素：

1. **太阳星座**：这是最常见的星座类型，根据出生日期确定。太阳星座通常与个人的基本性格特征和生活态度有关。

2. **月亮星座**：月亮星座代表了一个人的情感反应和内在感受，它与个人的情感需求和情绪波动有关。

3. **上升星座**（或称为升星）：这是根据出生时地平线上升起的星座确定的，它影响一个人的外在表现和他人对其的第一印象。

4. **行星位置**：除了太阳和月亮外，其他行星在出生时的位置也会影响个人的性格和运势。例如，金星影响爱情和审美，火星影响行动力和欲望等。

5. **宫位**：黄道十二宫代表了人生的不同领域，如个人财富、健康、事业、爱情等。行星落在不同的宫位会影响相应生活领域的运势。

6. **相位**：行星之间的相对位置和角度关系，如合相、对冲、三分相等，这些相位可以是和谐的也可以是紧张的，影响个人运势的正面或负面。

7. **运势周期**：占星术中还有各种周期性的概念，如行星逆行、新月、满月等，这些周期性事件被认为会影响人们的运势。

8. **个人星盘**：一个完整的个人星盘包含了所有上述因素，通过分析星盘可以更全面地了解一个人的运势。

9. **当前天象**：占星师还会考虑当前的天象，如行星的位置变化，以及它们与个人星盘中行星的相互作用。

10. **个人生活经历**：虽然占星术主要关注天体位置，但个人的决策和生活经历也会对运势产生影响。

进行星座运势分析时，通常会结合以上因素，通过专业的占星软件或咨询占星师来得到更详细的解读。然而，重要的是要记住，星座运势分析更多是一种娱乐方式，而不是科学预测方法。真正的运势受到多种复杂因素的影响，包括个人的选择和行动。

 */
